﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.IO;

namespace MyLibrary.Updater
{
    public class DownloadProgress : Form
    {
        private System.ComponentModel.IContainer components = null;
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            this.procCurrent = new System.Windows.Forms.ProgressBar();
            this.procTotal = new System.Windows.Forms.ProgressBar();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();

            this.procCurrent.Location = new System.Drawing.Point(12, 24);
            this.procCurrent.Name = "procCurrent";
            this.procCurrent.Size = new System.Drawing.Size(511, 23);
            this.procCurrent.TabIndex = 0;

            this.procTotal.Location = new System.Drawing.Point(12, 78);
            this.procTotal.Name = "procTotal";
            this.procTotal.Size = new System.Drawing.Size(511, 23);
            this.procTotal.TabIndex = 1;

            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 9);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(53, 12);
            this.label1.TabIndex = 2;
            this.label1.Text = "正在下载";

            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(12, 63);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(41, 12);
            this.label2.TabIndex = 3;
            this.label2.Text = "总进度";

            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(535, 128);
            this.ControlBox = false;
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.procTotal);
            this.Controls.Add(this.procCurrent);
            this.Name = "DownloadProgress";
            this.Text = "下载文件进度";
            this.ResumeLayout(false);
            this.PerformLayout();

            this.Load += new EventHandler(OnFormLoad);
        }

        #endregion

        private ProgressBar procCurrent;
        private ProgressBar procTotal;
        private Label label1;
        private Label label2;

        private bool isFinished = false;
        private bool isMandatoryUpdate = false;
        private List<DownloadFileInfo> lstDownloadFiles = null;
        private ManualResetEvent evtDownload = null;
        private ManualResetEvent evtPreDownload = null;
        private WebClient clientDownload = null;

        private long totalFileSize = 0;
        private long downloadFileSize = 0;

        public DownloadProgress(List<DownloadFileInfo> downloadfile)
            : this(downloadfile, false)
        {

        }

        public DownloadProgress(List<DownloadFileInfo> downloadfile, bool isMandatoryUpdate)
        {
            InitializeComponent();
            this.lstDownloadFiles = downloadfile;
            this.isMandatoryUpdate = isMandatoryUpdate;
        }

        private void OnFormLoad(object send, EventArgs e)
        {
            foreach (DownloadFileInfo file in lstDownloadFiles)
                totalFileSize += file.Size;

            evtDownload = new ManualResetEvent(true);
            evtDownload.Reset();
            Thread t = new Thread(new ThreadStart(ProcessDownload));
            t.Name = "download";
            t.Start();
        }

        private void ProcessDownload()
        {
            evtPreDownload = new ManualResetEvent(false);
            while (!evtDownload.WaitOne(0, false))
            {
                if (this.lstDownloadFiles.Count == 0)
                    break;
                DownloadFileInfo file = this.lstDownloadFiles[0];
                this.ShowCurrentDownloadFileName(file.FileFullName);
                //下载
                clientDownload = new WebClient();
                clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
                clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);
                evtPreDownload.Reset();
                clientDownload.DownloadFileAsync(new Uri(file.DownloadURL), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName + ".tmp"), file);
                //等待下载完成
                evtPreDownload.WaitOne();
                clientDownload.Dispose();
                clientDownload = null;
                //移除下载的文件
                this.lstDownloadFiles.Remove(file);
            }
            if (this.lstDownloadFiles.Count == 0)
                Exit(true);
            else
                Exit(false);
            evtDownload.Set();
        }

        void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            int totalTemp = (int)((downloadFileSize + e.BytesReceived) * 100 / totalFileSize);
            if (totalTemp > 100)
            {
                totalTemp = 100;
            }
            this.SetProcessBar(e.ProgressPercentage, totalTemp);
        }
        void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            DownloadFileInfo file = e.UserState as DownloadFileInfo;
            downloadFileSize += file.Size;
            this.SetProcessBar(0, (int)(downloadFileSize * 100 / totalFileSize));
            //Debug.WriteLine(String.Format("Finish Download:{0}", file.FileName));
            //替换现有文件
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileFullName);
            if (File.Exists(filePath))
            {
                if (File.Exists(filePath + ".old"))
                {
                    File.Delete(filePath + ".old");
                }
                File.Move(filePath, filePath + ".old");
            }

            File.Move(filePath + ".tmp", filePath);
            //继续下载其它文件
            evtPreDownload.Set();
        }


        delegate void ShowCurrentDownloadFileNameCallBack(string name);
        private void ShowCurrentDownloadFileName(string name)
        {
            if (this.label1.InvokeRequired)
            {
                ShowCurrentDownloadFileNameCallBack cb = new ShowCurrentDownloadFileNameCallBack(ShowCurrentDownloadFileName);
                this.Invoke(cb, new object[] { name });
            }
            else
            {
                this.label1.Text = name;
            }
        }

        delegate void SetProcessBarCallBack(int current, int total);
        private void SetProcessBar(int current, int total)
        {
            if (this.procCurrent.InvokeRequired)
            {
                SetProcessBarCallBack cb = new SetProcessBarCallBack(SetProcessBar);
                this.Invoke(cb, new object[] { current, total });
            }
            else
            {
                this.procCurrent.Value = current;
                this.procTotal.Value = total;
            }
        }

        delegate void ExitCallBack(bool success);
        private void Exit(bool success)
        {
            if (this.InvokeRequired)
            {
                ExitCallBack cb = new ExitCallBack(Exit);
                this.Invoke(cb, new object[] { success });
            }
            else
            {
                this.isFinished = success;
                this.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
                this.Close();
            }
        }
    }
}
